<template>
  <view class="results-container">
    <view class="results-image-wrapper">
      <!-- 背景图 (使用服务器返回的 picUrl) -->
      <img :src="photoPath" class="results-bg-image" @load="onImageLoad" />

      <!-- 穴位点、标签和连线 -->
      <view v-if="isImageLoaded" class="acupoint-container">
        <!-- 所有穴位点 -->
        <view
          v-for="acup in getCurrentGroupPoints()"
          :key="acup.id"
          class="point"
          :class="{ active: currentPart === acup.id }"
          :style="{
            left: getScaledPosition(acup.xaxis, 'x') + 'px',
            top: getScaledPosition(acup.yaxis, 'y') + 'px'
          }"></view>

        <!-- 连线和标签 (左右布局) -->
        <view class="labels-container labels-left">
          <view class="labels-wrapper">
            <view v-for="acup in getLeftLabels()" :key="`left-${acup.id}`" class="label-item">
              <text class="label" @click="switchAcupoint(acup)" :class="{ active: currentPart === acup.id }">
                {{ acup.acupoint_name }}
              </text>
              <view
                class="line"
                :class="{ active: currentPart === acup.id }"
                :style="{
                  width: getLineWidth(acup, true),
                  transform: getLineRotation(acup, true)
                }"></view>
            </view>
          </view>
        </view>
        <view class="labels-container labels-right">
          <view class="labels-wrapper">
            <view v-for="acup in getRightLabels()" :key="`right-${acup.id}`" class="label-item">
              <view
                class="line"
                :class="{ active: currentPart === acup.id }"
                :style="{
                  width: getLineWidth(acup, false),
                  transform: getLineRotation(acup, false)
                }"></view>
              <text class="label" @click="switchAcupoint(acup)" :class="{ active: currentPart === acup.id }">
                {{ acup.acupoint_name }}
              </text>
            </view>
          </view>
        </view>
      </view>
    </view>

    <view class="results-bottom-area">
      <view class="header">
        <view class="tag-group">
          <scroll-view scroll-x show-scrollbar="false">
            <text
              v-for="group in groupedAcupoints"
              :key="group.parentId"
              class="tag"
              :class="{ active: currentGroup === group.parentId }"
              @click="switchPart(group.parentId)"
              >{{ group.name }}</text
            >
          </scroll-view>
        </view>
        <view v-if="showRestart" class="restart-btn" @click="restart">
          <view class="icon-placeholder">{{ t('zhen.restart_short') }}</view>
          <text>{{ t('zhen.restart') }}</text>
        </view>
      </view>
      <scroll-view class="desc" scroll-y>
        {{ currentGroupDesc }}
      </scroll-view>
    </view>
  </view>
</template>

<script>
  import { useI18n } from 'vue-i18n'
  export default {
    name: 'ResultsPage',
    props: {
      photoPath: {
        type: String,
        required: true
      },
      acupointList: {
        type: Array,
        required: true
      },
      showRestart: {
        type: Boolean,
        required: false,
        default: true
      },
      linkTo: {
        type: Object,
        default: () => ({})
      }
    },
    data() {
      return {
        groupedAcupoints: [],
        currentGroup: null,
        currentPart: null,
        containerWidth: 0,
        containerHeight: 0,
        imageNaturalWidth: 0,
        imageNaturalHeight: 0,
        isImageLoaded: false,
        labelPositions: {},
        imageWrapperRect: null
      }
    },
    computed: {
      currentGroupDesc() {
        if (!this.currentPart || !this.acupointList.length) return this.t('zhen.select_acupoint_tip')
        const currentPoint = this.acupointList.find(item => item.id === this.currentPart)
        return currentPoint?.description || this.t('zhen.no_description')
      }
    },
    watch: {
      isImageLoaded(val) {
        if (val) {
          this.$nextTick(() => {
            this.getLabelPositions()
          })
        }
      },
      acupointList: {
        handler(newList) {
          if (newList && newList.length > 0) {
            this.handleAcupointGroup()
          }
        },
        immediate: true
      }
    }, // 在 created 钩子中赋值
    created() {
      const { t } = useI18n()
      this.t = t
    },
    mounted() {
      uni.onWindowResize(this.onWindowResize)
    },
    beforeDestroy() {
      uni.offWindowResize(this.onWindowResize)
    },
    methods: {
      onWindowResize() {
        setTimeout(() => {
          this.onImageLoad()
        }, 100)
      },

      restart() {
        this.$emit('restart')
      },
      handleAcupointGroup() {
        const groups = {}
        this.acupointList.forEach(item => {
          if (!groups[item.body_part_id]) {
            groups[item.body_part_id] = {
              parentId: item.body_part_id,
              name: item.body_part_name,
              items: []
            }
          }
          groups[item.body_part_id].items.push(item)
        })
        this.groupedAcupoints = Object.values(groups)

        if (this.groupedAcupoints.length > 0) {
          this.switchPart(this.groupedAcupoints[0].parentId)
        } else {
          this.currentGroup = null
          this.currentPart = null
        }
      },
      switchPart(parentId) {
        this.currentGroup = parentId
        const currentGroupData = this.groupedAcupoints.find(g => g.parentId === parentId)
        if (currentGroupData?.items.length > 0) {
          this.currentPart = currentGroupData.items[0].id
        }
        this.$nextTick(() => {
          this.getLabelPositions()
        })
      },
      switchAcupoint(acup) {
        this.currentPart = acup.id
      },
      async onImageLoad() {
        this.isImageLoaded = false

        if (!this.photoPath) return
        try {
          const imgInfo = await new Promise((resolve, reject) => {
            uni.getImageInfo({ src: this.photoPath, success: resolve, fail: reject })
          })
          this.imageNaturalWidth = imgInfo.width
          this.imageNaturalHeight = imgInfo.height

          const data = await new Promise(resolve => {
            uni
              .createSelectorQuery()
              .in(this)
              .select('.results-image-wrapper')
              .boundingClientRect(d => resolve(d))
              .exec()
          })
          if (data) {
            this.containerWidth = data.width
            this.containerHeight = data.height
            this.imageWrapperRect = data
            this.isImageLoaded = true
          }
        } catch (e) {
          console.error('onImageLoad 失败:', e)
          uni.showToast({ title: this.t('zhen.image_load_failed'), icon: 'none' })
        }
      },
      getCurrentGroupPoints() {
        if (!this.currentGroup) return []
        return this.acupointList.filter(item => item.body_part_id === this.currentGroup)
      },
      getLeftLabels() {
        const points = this.getCurrentGroupPoints()
        return points.slice(0, Math.ceil(points.length / 2))
      },
      getRightLabels() {
        const points = this.getCurrentGroupPoints()
        return points.slice(Math.ceil(points.length / 2))
      },
      getScaledPosition(value, axis) {
        if (!this.containerWidth || !this.imageNaturalWidth) return 0
        const cRatio = this.containerWidth / this.containerHeight
        const iRatio = this.imageNaturalWidth / this.imageNaturalHeight
        let dWidth,
          dHeight,
          offsetX = 0,
          offsetY = 0
        if (cRatio > iRatio) {
          dHeight = this.containerHeight
          dWidth = this.imageNaturalWidth * (dHeight / this.imageNaturalHeight)
          offsetX = (this.containerWidth - dWidth) / 2
        } else {
          dWidth = this.containerWidth
          dHeight = this.imageNaturalHeight * (dWidth / this.imageNaturalWidth)
          offsetY = (this.containerHeight - dHeight) / 2
        }
        const scaleX = dWidth / this.imageNaturalWidth
        const scaleY = dHeight / this.imageNaturalHeight
        return axis === 'x' ? value * scaleX + offsetX : value * scaleY + offsetY
      },

      getLabelPositions() {
        if (!this.imageWrapperRect) {
          setTimeout(() => this.getLabelPositions(), 100)
          return
        }

        setTimeout(() => {
          const query = uni.createSelectorQuery().in(this)
          query
            .selectAll('.label-item')
            .boundingClientRect(itemsData => {
              if (itemsData && itemsData.length) {
                const allLabels = [...this.getLeftLabels(), ...this.getRightLabels()]
                const newPositions = {}
                const containerRect = this.imageWrapperRect

                itemsData.forEach((itemRect, index) => {
                  const point = allLabels[index]
                  if (point) {
                    // 使用 acupoint 的唯一 id作为 key
                    newPositions[point.id] = {
                      ...itemRect,
                      top: itemRect.top - containerRect.top,
                      left: itemRect.left - containerRect.left,
                      right: itemRect.right - containerRect.left,
                      bottom: itemRect.bottom - containerRect.top
                    }
                  }
                })
                this.labelPositions = newPositions
              }
            })
            .exec()
        }, 150)
      },

      getLineWidth(acup, isLeft) {
        if (!this.labelPositions[acup.id]) return '0px'
        const pointX = this.getScaledPosition(acup.xaxis, 'x')
        const pointY = this.getScaledPosition(acup.yaxis, 'y')
        const labelPos = this.labelPositions[acup.id]

        const labelY = labelPos.top + labelPos.height / 2
        const labelX = isLeft ? labelPos.right : labelPos.left

        const dx = pointX - labelX
        const dy = pointY - labelY
        return Math.sqrt(dx * dx + dy * dy) + 'px'
      },

      getLineRotation(acup, isLeft) {
        if (!this.labelPositions[acup.id]) return 'rotate(0deg)'

        const pointX = this.getScaledPosition(acup.xaxis, 'x')
        const pointY = this.getScaledPosition(acup.yaxis, 'y')
        const labelPos = this.labelPositions[acup.id]

        const labelY = labelPos.top + labelPos.height / 2
        const labelX = isLeft ? labelPos.right : labelPos.left

        const dx = pointX - labelX
        const dy = pointY - labelY

        // 计算基础角度
        let angle = Math.atan2(dy, dx) * (180 / Math.PI)

        if (!isLeft) {
          // angle += 180; // 效果与 angle -= 180 相同
          // 实际上，正确的物理旋转应该是从180度（线指向左）转到目标角度theta
          // 旋转量 = theta - 180。这在视觉上等同于 theta + 180
        }
        if (!isLeft) {
          angle += 180
        }

        return `rotate(${angle}deg)`
      }
    }
  }
</script>

<style lang="scss" scoped>
  .results-container {
    background-color: #f5f5f5;
  }
  .results-image-wrapper {
    position: relative;
  }
  .results-bg-image {
    width: 100%;
    display: block;
  }
  ::v-deep .results-bg-image > img {
    opacity: 1 !important;
  }

  .results-bottom-area {
    background: #fff;
    padding: 10px;
    display: flex;
    flex-direction: column;
    position: relative;
    box-shadow: 0 -2px 5px rgba(0, 0, 0, 0.05);
    padding-bottom: constant(safe-area-inset-bottom);
    padding-bottom: env(safe-area-inset-bottom);
    flex-shrink: 0;
    max-height: 35vh;
  }
  .header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 8px;
  }
  .tag-group {
    flex: 1;
    overflow: hidden;
    scroll-view {
      width: 100%;
      white-space: nowrap;
    }
    .tag {
      display: inline-block;
      padding: 6px 10px;
      margin-right: 10px;
      border-radius: 7px;
      font-size: 14px;
      background: #f5f5f5;
      color: #666;
      transition: all 0.2s ease;
      &.active {
        background: #9177ff;
        color: #fff;
        font-weight: bold;
      }
    }
  }
  .restart-btn {
    border: 1px solid #333;
    display: flex;
    align-items: center;
    margin-left: 10px;
    border-radius: 6px;
    padding: 5px;
    flex-shrink: 0;
    .icon-placeholder {
      width: 20px;
      height: 20px;
      font-size: 12px;
      margin-right: 4px;
      background-color: #333;
      border-radius: 50%;
      display: flex;
      justify-content: center;
      align-items: center;
      color: #fff;
    }
    text {
      font-size: 14px;
      color: #333;
      font-weight: 500;
    }
  }
  .desc {
    height: 80px;
    font-size: 14px;
    line-height: 1.6;
    overflow-y: auto;
    color: #333;
    flex-shrink: 1;
  }
  .results-action-buttons {
    position: absolute;
    top: 20px;
    left: 0;
    right: 0;
    display: flex;
    justify-content: center;
    gap: 20px;
    z-index: 20;
  }
  .action-btn {
    background: rgba(232, 113, 113, 1);
    padding: 6px 18px;
    border-radius: 14px;
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
    text {
      color: #fff;
      font-size: 16px;
      font-weight: 500;
    }
    &:active {
      opacity: 0.8;
    }
  }
  .acupoint-container {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
  }
  .point {
    position: absolute;
    width: 6px;
    height: 6px;
    background-color: #9177ff;
    border: 1px solid white;
    border-radius: 50%;
    transform: translate(-50%, -50%);
    pointer-events: auto;
    cursor: pointer;
    z-index: 15;
    transition: all 0.2s ease;
    &.active {
      background-color: #ff3e3e;
      width: 10px;
      height: 10px;
    }
  }
  .labels-container {
    position: absolute;
    top: 0;
    bottom: 0;
    width: 120px;
    display: flex;
    align-items: center;
    z-index: 13;
    .labels-wrapper {
      width: 100%;
      display: flex;
      flex-direction: column;
      justify-content: center;
      height: 80%;
    }
  }
  .label-item {
    position: relative;
    margin: 5px 0;
    display: flex;
    align-items: center;
    pointer-events: auto;
    width: 70px;
    .label {
      width: 70px;
      padding: 3px 0;
      background-color: rgba(145, 119, 255, 0.8);
      color: #fff;
      font-size: 12px;
      border-radius: 4px;
      white-space: nowrap;
      text-align: center;
      transition: all 0.2s ease;
      cursor: pointer;
      &.active {
        background-color: rgba(255, 62, 62, 0.9);
        transform: scale(1.1);
        font-weight: bold;
      }
    }
    .line {
      position: absolute;
      height: 1px;
      background-color: rgba(145, 119, 255, 0.8);
      transition: all 0.2s ease;
      &.active {
        background-color: rgba(255, 62, 62, 0.9);
        height: 2px;
      }
    }
  }
  .labels-left {
    left: 15px;
    .label-item {
      .line {
        left: 100%;
        transform-origin: left center;
      }
    }
  }
  .labels-right {
    right: 15px;
    .label-item {
      margin-left: auto;

      .line {
        right: 100%;
        transform-origin: right center;
      }
    }
  }
</style>
